home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / lfs / lfsFileLayout.c < prev    next >
C/C++ Source or Header  |  1991-08-08  |  50KB  |  1,609 lines

  1. /* 
  2.  * lfsFileLayout.c --
  3.  *
  4.  *    Control the writing, cleaning, and checkpointing of files and 
  5.  *    file descriptors.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/lfs/RCS/lfsFileLayout.c,v 1.10 91/08/08 17:47:02 mendel Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <lfsInt.h>
  22. #include <lfsSeg.h>
  23. #include <lfsFileLayout.h>
  24. #include <lfsDesc.h>
  25. #include <lfsDescInt.h>
  26.  
  27. #include <fsdm.h>
  28. #include <fscache.h>
  29. #include <rpc.h>
  30.  
  31. #ifdef TRACING
  32. #include <trace.h>
  33. Trace_Header lfsTraceHdr;
  34. Trace_Header *lfsTraceHdrPtr = &lfsTraceHdr;
  35. int lfsTraceLength = 1000;
  36. typedef struct LfsTraceRecord {
  37.     int    fileNumber;
  38.     LfsDiskAddr diskAddr;
  39.     ReturnStatus status;
  40.     int  curTruncVersion;
  41. } LfsTraceRecord;
  42. #endif
  43.  
  44. #define    LOCKPTR    &lfsPtr->lock
  45.  
  46. Boolean    lfsFileLayoutDebug = FALSE;
  47.  
  48. typedef struct FileSegLayout {
  49.     int     numDescSlotsLeft;    /* Number of slots left in descriptor block. */
  50.     LfsFileDescriptor *descBlockPtr;        
  51.                 /* Pointer to next slot in descriptor block. */
  52.     LfsDiskAddr descDiskAddr;     /* Disk address of descriptor block. */
  53.     int maxElements;          /* The maximum number of elements. */
  54.     List_Links    fileList; /* List of files in this segment. */
  55.     List_Links  blockList; /* List of cache blocks laidout in
  56.                        * this segment.  */
  57.     Fscache_FileInfo    *activeFilePtr;    /* File current being written. */
  58.     List_Links    dirLogListHdr;    /* List of directory block blocks being 
  59.                  * written. */
  60. } FileSegLayout;
  61.  
  62. static Boolean PlaceFileInSegment _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr, 
  63.     Fscache_FileInfo *cacheInfoPtr, LfsFileLayout *layoutPtr, 
  64.     int token, FileSegLayout *segLayoutDataPtr));
  65.  
  66. static Boolean BlockMatch _ARGS_((Fscache_Block *blockPtr, 
  67.                 ClientData clientData));
  68.  
  69. static void DirLogInit _ARGS_((Lfs *lfsPtr));
  70. static void DirLogDestory _ARGS_((Lfs *lfsPtr));
  71. static void NewDirLogBlock _ARGS_((Lfs *lfsPtr));
  72. static LfsDirOpLogEntry *FindLogEntry _ARGS_((Lfs *lfsPtr, int logSeqNum));
  73. static Boolean AddDirLogBlocks _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr, 
  74.             FileSegLayout *segLayoutDataPtr));
  75. static void FreeDirLogBlocks _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr,
  76.             FileSegLayout *segLayoutDataPtr));
  77.  
  78. extern ReturnStatus LfsFileLayoutAttach _ARGS_((Lfs *lfsPtr, 
  79.             int checkPointSize, char *checkPointPtr));
  80. extern Boolean LfsFileLayoutProc _ARGS_((LfsSeg *segPtr, int flags, 
  81.             ClientData *clientDataPtr));
  82. extern Boolean LfsFileLayoutCheckpoint _ARGS_((LfsSeg *segPtr, int flags, 
  83.             char *checkPointPtr, int *checkPointSizePtr, 
  84.             ClientData *clientDataPtr));
  85. extern void LfsFileLayoutWriteDone _ARGS_((LfsSeg *segPtr, int flags, 
  86.             ClientData *clientDataPtr));
  87. extern Boolean LfsFileLayoutClean _ARGS_((LfsSeg *segPtr, int *sizePtr, 
  88.             int *numCacheBlocksPtr, ClientData *clientDataPtr));
  89.  
  90. extern ReturnStatus LfsFileLayoutDetach _ARGS_((Lfs *lfsPtr));
  91.  
  92. static LfsSegIoInterface layoutIoInterface = 
  93.     { LfsFileLayoutAttach, LfsFileLayoutProc, LfsFileLayoutClean,
  94.       LfsFileLayoutCheckpoint, LfsFileLayoutWriteDone, 
  95.       LfsFileLayoutDetach, 0};
  96.  
  97. #define    WRITEBACK_TOKEN        0
  98. #define    CLEANING_TOKEN        1
  99. #define    CHECKPOINT_TOKEN    2
  100.  
  101. /*
  102.  *----------------------------------------------------------------------
  103.  *
  104.  * LfsFileLayoutInit --
  105.  *
  106.  *    Initialize the call back structure is for LfsFileLayout().  
  107.  *
  108.  * Results:
  109.  *    None
  110.  *    
  111.  * Side effects:
  112.  *
  113.  *----------------------------------------------------------------------
  114.  */
  115.  
  116. void
  117. LfsFileLayoutInit()
  118. {
  119.     LfsSegIoRegister(LFS_FILE_LAYOUT_MOD,&layoutIoInterface);
  120. #ifdef TRACING
  121.     Trace_Init(lfsTraceHdrPtr, lfsTraceLength, sizeof(LfsTraceRecord),
  122.         TRACE_NO_TIMES);
  123. #endif
  124. }
  125.  
  126. #ifdef TRACING
  127. ReturnStatus
  128. Lfs_PrintRec(clientData, event, printHeaderFlag)
  129.     ClientData clientData;    /* Client data in the trace record */
  130.     int event;            /* Type, or event, from the trace record */
  131.     Boolean printHeaderFlag;    /* If TRUE, a header line is printed */
  132. {
  133.     LfsTraceRecord *recPtr = (LfsTraceRecord *) clientData;
  134.     if (recPtr != (LfsTraceRecord *) NIL) { 
  135.     printf("<%d,%d,%d,%d>\n", recPtr->fileNumber, recPtr->blockNumber,
  136.             LfsDiskAddrToOffset(recPtr->diskAddr), recPtr->found);
  137.     }
  138.     return SUCCESS;
  139. }
  140. void
  141. Lfs_PrintTrace(numRecs)
  142.     int numRecs;
  143. {
  144.     if (numRecs < 0) {
  145.     numRecs = lfsTraceLength;
  146.     }
  147.     printf("LFS TRACE\n");
  148.     (void)Trace_Print(lfsTraceHdrPtr, numRecs, Lfs_PrintRec);
  149. }
  150. #endif
  151.  
  152. /*
  153.  *----------------------------------------------------------------------
  154.  *
  155.  * FileLayoutAttach --
  156.  *
  157.  *    Attach routine for file layout module. Creates and initializes the
  158.  *    data structures used for writeback for this file system.
  159.  *
  160.  * Results:
  161.  *    SUCCESS if attaching is going ok.
  162.  *
  163.  * Side effects:
  164.  *    Many
  165.  *
  166.  *----------------------------------------------------------------------
  167.  */
  168. /*ARGSUSED*/
  169. ReturnStatus
  170. LfsFileLayoutAttach(lfsPtr, checkPointSize, checkPointPtr)
  171.     Lfs   *lfsPtr;         /* File system for attach. */
  172.     int   checkPointSize;    /* Size of checkpoint data. */
  173.     char  *checkPointPtr;     /* Data from last checkpoint before shutdown. */
  174. {
  175.     LfsFileLayout          *layoutPtr = &(lfsPtr->fileLayout);
  176.     LfsFileLayoutParams          *paramsPtr = &(lfsPtr->superBlock.fileLayout);
  177.     /*
  178.      * Initialize the filelayout structures for this file system.
  179.      */
  180.     layoutPtr->params = *paramsPtr;
  181.  
  182.     LfsDescCacheInit(lfsPtr);
  183.     Sync_LockInitDynamic(&(lfsPtr->logLock), "LfsLogLock");
  184.     DirLogInit(lfsPtr);
  185.  
  186.     return SUCCESS;
  187. }
  188.  
  189.  
  190. /*
  191.  *----------------------------------------------------------------------
  192.  *
  193.  * LfsFileLayoutDetach --
  194.  *
  195.  *    Detach routine for file layout module. 
  196.  *
  197.  * Results:
  198.  *    SUCCESS if attaching is going ok.
  199.  *
  200.  * Side effects:
  201.  *    Many
  202.  *
  203.  *----------------------------------------------------------------------
  204.  */
  205. /*ARGSUSED*/
  206. ReturnStatus
  207. LfsFileLayoutDetach(lfsPtr)
  208.     Lfs   *lfsPtr;         /* File system for attach. */
  209. {
  210.  
  211.     LfsDescCacheDestory(lfsPtr);
  212.     DirLogDestory(lfsPtr);
  213.  
  214.     return SUCCESS;
  215. }
  216.  
  217.  
  218.  
  219.  
  220. /*
  221.  *----------------------------------------------------------------------
  222.  *
  223.  * LfsFileLayoutProc --
  224.  *
  225.  *    Routine to handle layout of file block in segments.
  226.  *
  227.  * Results:
  228.  *    TRUE if more data needs to be written, FALSE if this module is
  229.  *    happy for the time being.
  230.  *
  231.  * Side effects:
  232.  *    
  233.  *
  234.  *----------------------------------------------------------------------
  235.  */
  236.  
  237. Boolean
  238. LfsFileLayoutProc(segPtr, flags, clientDataPtr)
  239.     LfsSeg *segPtr;        /* Segment to place data blocks in. */
  240.     int    flags;        /* Cleaning flags */
  241.     ClientData    *clientDataPtr;
  242. {
  243.     Lfs            *lfsPtr =   segPtr->lfsPtr;
  244.     LfsFileLayout    *layoutPtr = &(lfsPtr->fileLayout);
  245.     Fscache_FileInfo    *cacheInfoPtr;
  246.     Boolean        full, fsyncOnly;
  247.     FileSegLayout  *segLayoutDataPtr;
  248.     int          token;
  249.  
  250.      /*
  251.       * Next spill the file with dirty blocks into the segment. 
  252.       */
  253.      LFS_STATS_INC(lfsPtr->stats.layout.calls);
  254.      full = FALSE;
  255.  
  256.      fsyncOnly = ((flags & (LFS_CLEANING_LAYOUT|LFS_CHECKPOINT_LAYOUT)) == 0);
  257.      if (flags & LFS_CLEANING_LAYOUT) {
  258.      token = CLEANING_TOKEN;
  259.      } else if (flags & LFS_CHECKPOINT_LAYOUT) {
  260.      token = CHECKPOINT_TOKEN;
  261.      } else {
  262.      token = WRITEBACK_TOKEN;
  263.      }
  264.      if (*clientDataPtr == (ClientData) NIL) {
  265.  
  266.     /*
  267.      * Allocate a FileSegLayout data structure for this segment. 
  268.      */
  269.      segLayoutDataPtr = (FileSegLayout *) malloc(sizeof(FileSegLayout));
  270.      *clientDataPtr = (ClientData) segLayoutDataPtr;
  271.      segLayoutDataPtr->numDescSlotsLeft = 0;
  272.      segLayoutDataPtr->maxElements = LfsSegSizeInBlocks(lfsPtr);
  273.      List_Init(&segLayoutDataPtr->fileList);
  274.      List_Init(&segLayoutDataPtr->blockList);
  275.      segLayoutDataPtr->activeFilePtr = (Fscache_FileInfo *) NIL;
  276.      List_Init(&segLayoutDataPtr->dirLogListHdr);
  277.      } else {
  278.      segLayoutDataPtr = (FileSegLayout *) *clientDataPtr;
  279.      }
  280.      cacheInfoPtr = (Fscache_FileInfo *) NIL;
  281.      /*
  282.       * Choose the first file. If the last call to layout data into this
  283.       * segment ended with a partially layed out file, start with that file.
  284.       */
  285.      if (segLayoutDataPtr->activeFilePtr == (Fscache_FileInfo *) NIL) { 
  286.       full = AddDirLogBlocks(lfsPtr, segPtr, segLayoutDataPtr);
  287.       if (!full) { 
  288.           cacheInfoPtr = Fscache_GetDirtyFile(lfsPtr->domainPtr->backendPtr, 
  289.             fsyncOnly, LfsFileMatch, (ClientData) token);
  290.       }
  291.      } else {
  292.      cacheInfoPtr = segLayoutDataPtr->activeFilePtr;
  293.      }
  294.      while (!full && (cacheInfoPtr != (Fscache_FileInfo *) NIL)) {
  295.        LFS_STATS_INC(lfsPtr->stats.layout.dirtyFiles);
  296.        full = PlaceFileInSegment(lfsPtr, segPtr, cacheInfoPtr, layoutPtr,
  297.             token,  segLayoutDataPtr);
  298.        if (full) {
  299.            LFS_STATS_INC(lfsPtr->stats.layout.filledRegion);
  300.            segLayoutDataPtr->activeFilePtr = cacheInfoPtr;
  301.            break;
  302.        }
  303.        List_Insert((List_Links *) cacheInfoPtr, 
  304.                 LIST_ATREAR(&segLayoutDataPtr->fileList));
  305.        full = AddDirLogBlocks(lfsPtr, segPtr, segLayoutDataPtr);
  306.        if (!full) { 
  307.            cacheInfoPtr = Fscache_GetDirtyFile(
  308.             lfsPtr->domainPtr->backendPtr, 
  309.             FALSE, LfsFileMatch, (ClientData) token);
  310.        }
  311.     }
  312.     if (!full && List_IsEmpty(&segLayoutDataPtr->fileList) &&
  313.        List_IsEmpty(&segLayoutDataPtr->dirLogListHdr)) { 
  314.     free((char *) *clientDataPtr);
  315.     *clientDataPtr = (ClientData) NIL;
  316.     }
  317.     return full;
  318.  
  319. }
  320.  
  321.  
  322.  
  323. /*
  324.  *----------------------------------------------------------------------
  325.  *
  326.  * FileLayoutCheckpoint --
  327.  *
  328.  *    Routine to handle checkpointing of the file layout data.
  329.  *
  330.  * Results:
  331.  *    TRUE if more data needs to be written, FALSE if this module is
  332.  *    checkpointed.
  333.  *
  334.  * Side effects:
  335.  *    Many
  336.  *
  337.  *----------------------------------------------------------------------
  338.  */
  339. /*ARGSUSED*/
  340. Boolean
  341. LfsFileLayoutCheckpoint(segPtr, flags, checkPointPtr,  checkPointSizePtr,
  342.             clientDataPtr)
  343.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  344.     int       flags;        /* Flags. */
  345.     char   *checkPointPtr;      /* Buffer to write checkpoint data. */
  346.     int       *checkPointSizePtr;  /* Bytes added to the checkpoint area.*/
  347.     ClientData *clientDataPtr;
  348. {
  349.     Boolean full;
  350.  
  351.     /*
  352.      * Write-back everything that is dirty.
  353.      */
  354.     full = LfsFileLayoutProc(segPtr, LFS_CHECKPOINT_LAYOUT, clientDataPtr);
  355.     return full;
  356.  
  357. }
  358.  
  359. /*
  360.  *----------------------------------------------------------------------
  361.  *
  362.  * FileLayoutWriteDone --
  363.  *
  364.  *    Routine to handle finishing of file layout writes
  365.  *
  366.  * Results:
  367.  *    None
  368.  *
  369.  * Side effects:
  370.  *    Many
  371.  *
  372.  *----------------------------------------------------------------------
  373.  */
  374. /*ARGSUSED*/
  375. void
  376. LfsFileLayoutWriteDone(segPtr, flags, clientDataPtr)
  377.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  378.     int       flags;        /* Flags for checkpoint */
  379.     ClientData *clientDataPtr;
  380. {
  381.     Lfs          *lfsPtr = segPtr->lfsPtr;
  382.     LfsSegElement *bufferPtr = LfsSegGetBufferPtr(segPtr);
  383.     char     *summaryPtr =  LfsSegGetSummaryPtr(segPtr);
  384.     char     *limitPtr;
  385.     Fscache_Block *blockPtr;
  386.     Fscache_FileInfo *cacheInfoPtr;
  387.     FileSegLayout  *segLayoutDataPtr;
  388.  
  389.     limitPtr = summaryPtr + LfsSegSummaryBytesLeft(segPtr); 
  390.      while (summaryPtr < limitPtr) { 
  391.     switch (*(unsigned short *) summaryPtr) {
  392.     case LFS_FILE_LAYOUT_DESC: {
  393. #ifdef notdef
  394.         LfsFileDescriptor    *descPtr;
  395.         int        i;
  396.         /*
  397.          * A block of descriptors.  For each descriptor we now can 
  398.          * update the descriptor map to point the descriptor at it.
  399.          */
  400.          descPtr = (LfsFileDescriptor *) bufferPtr->address;
  401.          for (i = 0; (i < layoutPtr->params.descPerBlock) && 
  402.              (descPtr->common.flags != 0); i++) {
  403.          UpdateIndex(lfsPtr, descPtr->fileNumber, 
  404.                     LfsSegDiskAddress(segPtr,bufferPtr));
  405.          }
  406. #endif
  407.          LFS_STATS_INC(lfsPtr->stats.layout.descBlockWritten);
  408.          LfsDescCacheBlockRelease(segPtr->lfsPtr, bufferPtr->clientData, 
  409.                 FALSE);
  410.          bufferPtr++;
  411.          summaryPtr += sizeof(LfsFileLayoutDesc);
  412.          break;
  413.     }
  414.     case LFS_FILE_LAYOUT_DATA:  {
  415.         LfsFileLayoutSummary *fileSumPtr;
  416.         /* 
  417.          * All these records should be pointing to a cache blocks which
  418.          * must be released.
  419.          */
  420.         fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  421.         bufferPtr += fileSumPtr->numDataBlocks;
  422.         summaryPtr += (sizeof(LfsFileLayoutSummary) + 
  423.                fileSumPtr->numDataBlocks * sizeof(int));
  424.         break;
  425.     }
  426.     case LFS_FILE_LAYOUT_DIR_LOG: {
  427.         LfsFileLayoutLog    *logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  428.          /*
  429.           * Because we copied and truncated the log during layout we 
  430.           * don't need to do anything on write complete.
  431.           */
  432.         summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  433.         bufferPtr += logSumPtr->numDataBlocks;
  434.         break;
  435.     }
  436.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  437.     case LFS_FILE_LAYOUT_INDIRECT: 
  438.     default:
  439.         panic("Bad file block type in summary block");
  440.     }
  441.     }
  442.     LfsSegSetBufferPtr(segPtr, bufferPtr);
  443.     if (*clientDataPtr != (ClientData) NIL) {
  444.     LFS_STATS_INC(lfsPtr->stats.layout.segWrites);
  445.     segLayoutDataPtr = (FileSegLayout *) *clientDataPtr;
  446.     FreeDirLogBlocks(lfsPtr, segPtr, segLayoutDataPtr);
  447.     while (!List_IsEmpty(&segLayoutDataPtr->blockList)) {
  448.         blockPtr = (Fscache_Block *)
  449.                 List_First(&segLayoutDataPtr->blockList);
  450.         List_Remove((List_Links *)blockPtr);
  451.         LFS_STATS_INC(lfsPtr->stats.layout.cacheBlocksWritten);
  452.         Fscache_ReturnDirtyBlock(blockPtr, SUCCESS);
  453.     }
  454.     while (!List_IsEmpty(&segLayoutDataPtr->fileList)) {
  455.         cacheInfoPtr = 
  456.         (Fscache_FileInfo *) List_First(&segLayoutDataPtr->fileList);
  457.         List_Remove((List_Links *)cacheInfoPtr);
  458.         LFS_STATS_INC(lfsPtr->stats.layout.filesWritten);
  459.         Fscache_ReturnDirtyFile(cacheInfoPtr, TRUE);
  460.     }
  461.     if (segLayoutDataPtr->activeFilePtr != (Fscache_FileInfo *) NIL) {
  462.         Fscache_ReturnDirtyFile(segLayoutDataPtr->activeFilePtr, TRUE);
  463.     }
  464.     free((char *) *clientDataPtr);
  465.     *clientDataPtr = (ClientData) NIL;
  466.     }
  467.     return;
  468.  
  469. }
  470.  
  471.  
  472. /*
  473.  *----------------------------------------------------------------------
  474.  *
  475.  * FileLayoutClean --
  476.  *
  477.  *    Routine to handle cleaning of file data blocks.
  478.  *
  479.  * Results:
  480.  *    TRUE if we couldn't clean the segment.
  481.  *
  482.  * Side effects:
  483.  *    
  484.  *
  485.  *----------------------------------------------------------------------
  486.  */
  487.  
  488. Boolean
  489. LfsFileLayoutClean(segPtr, sizePtr, numCacheBlocksPtr, clientDataPtr)
  490.     LfsSeg *segPtr;    /* Segment containing data to clean. */
  491.     int       *sizePtr;
  492.     int    *numCacheBlocksPtr;
  493.     ClientData *clientDataPtr;
  494. {
  495.     Lfs           *lfsPtr = segPtr->lfsPtr;
  496.     LfsFileLayout  *layoutPtr = &(lfsPtr->fileLayout);
  497.     LfsFileLayoutSummary  *fileSumPtr;
  498.     char    *summaryPtr, *limitPtr;
  499.     int  blockOffset, fsBlocks;
  500.     LfsDiskAddr address;
  501.     ReturnStatus    status;
  502.     Boolean    error;
  503.  
  504.      error = FALSE;
  505.      fsBlocks = LfsBytesToBlocks(lfsPtr, FS_BLOCK_SIZE);
  506.      summaryPtr =  LfsSegGetSummaryPtr(segPtr);
  507.      limitPtr = summaryPtr + LfsSegSummaryBytesLeft(segPtr);
  508.      address = LfsSegDiskAddress(segPtr, LfsSegGetBufferPtr(segPtr));
  509.      blockOffset = 0;
  510.      LFS_STATS_INC(lfsPtr->stats.layout.cleanings);
  511.      while ((summaryPtr < limitPtr) && !error) { 
  512.     switch (*(unsigned short *) summaryPtr) {
  513.     case LFS_FILE_LAYOUT_DESC: {
  514.         LfsDiskAddr diskAddr;
  515.         int        fileNumber;
  516.         int        slot, size;
  517.         LfsFileDescriptor    *descPtr;
  518.         char        *blockStartPtr;
  519.         ClientData descCachePtr = (ClientData) NIL;
  520.         /*
  521.          * A block of descriptors.  For each descriptor that is live
  522.          * (being pointed to by the descriptor map) we bring it into
  523.          * the system and mark it as dirty. 
  524.          */
  525.         LFS_STATS_INC(lfsPtr->stats.layout.descBlocksCleaned);
  526.         size = layoutPtr->params.descPerBlock * sizeof(LfsFileDescriptor);
  527.         blockOffset += LfsBytesToBlocks(lfsPtr, size);
  528.         blockStartPtr = LfsSegFetchBytes(segPtr, 
  529.                 segPtr->curBlockOffset + blockOffset, size);
  530.         descPtr = (LfsFileDescriptor *)blockStartPtr;
  531.         for (slot = 0; slot < layoutPtr->params.descPerBlock; slot++) {
  532.         Fs_FileID fileID;
  533.         Fsio_FileIOHandle *newHandlePtr;
  534.         LfsDiskAddr newDiskAddr;
  535.         /*
  536.          * The descriptor block is terminated by an unallocated
  537.          * descriptor.
  538.          */
  539.         if (!(descPtr[slot].common.flags & FSDM_FD_ALLOC)) {
  540.             break;
  541.         }
  542.         fileNumber = descPtr[slot].fileNumber;
  543.         status = LfsDescMapGetDiskAddr(lfsPtr, fileNumber, &diskAddr);
  544.         /*
  545.          * If the file is not allocated or this descriptor is not
  546.          * the most current copy, skip it.
  547.          */
  548.         LfsDiskAddrPlusOffset(address,-blockOffset, &newDiskAddr);
  549.         if ((status == FS_FILE_NOT_FOUND) || 
  550.             ((status == SUCCESS) && 
  551.               !LfsSameDiskAddr(diskAddr, newDiskAddr))) {
  552.             continue;
  553.         }
  554.         if (status != SUCCESS) {
  555.             LfsError(lfsPtr, status, 
  556.             "Bad file number in descriptor block.\n");
  557.             continue;
  558.         }
  559.             LFS_STATS_INC(lfsPtr->stats.layout.descCopied);
  560.         if (descCachePtr == (ClientData) NIL) {
  561.             char *blockAddrPtr;
  562.             /*
  563.              * We get to read it into the cache if its not already
  564.              * there. 
  565.              */
  566.             blockAddrPtr = blockStartPtr;
  567.             descCachePtr = LfsDescCacheBlockInit(lfsPtr, diskAddr, 
  568.                             TRUE, 
  569.                             &blockAddrPtr);
  570.             if (descCachePtr == (ClientData) NIL) {
  571.             printf("Can't fetch descriptor block\n");
  572.             error = TRUE;
  573.             break;
  574.             }
  575.         }
  576.         /*
  577.          * Grab a handle for this file.
  578.          */
  579.         fileID.type = FSIO_LCL_FILE_STREAM;
  580.         fileID.serverID = rpc_SpriteID;
  581.         fileID.major = lfsPtr->domainPtr->domainNumber;
  582.         fileID.minor = fileNumber;
  583.         status = Fsio_LocalFileHandleInit(&fileID, (char *) NIL, 
  584.                     (Fsdm_FileDescriptor *) NIL, TRUE, 
  585.                     &newHandlePtr);
  586.         if (status == FS_WOULD_BLOCK) {
  587.             error = TRUE;
  588.             break;
  589.         }
  590.         if (status == FS_FILE_REMOVED) {
  591.             continue;
  592.         }
  593.         if (status != SUCCESS) {
  594.             LfsError(lfsPtr, status, 
  595.                 "Can't get handle to clean file\n");
  596.         }
  597.         *sizePtr += sizeof(LfsFileDescriptor);
  598.         Fscache_PutFileOnDirtyList(&newHandlePtr->cacheInfo, 
  599.                     (int)(FSCACHE_FILE_BEING_CLEANED |
  600.                     FSCACHE_FILE_DESC_DIRTY));
  601.         Fsutil_HandleRelease(newHandlePtr, TRUE);
  602.         }
  603.         if (descCachePtr != (ClientData) NIL) {
  604.         LfsDescCacheBlockRelease(lfsPtr, descCachePtr, TRUE);
  605.         }
  606.         /*
  607.          * Skip over the summary bytes describing this block. 
  608.          */
  609.         summaryPtr += sizeof(LfsFileLayoutDesc);
  610.         break;
  611.     }
  612.     case LFS_FILE_LAYOUT_DATA: {
  613.         LfsDiskAddr diskAddress;
  614.         int        *blockArray;
  615.         int             startBlockOffset, i;
  616.         unsigned short    curTruncVersion;
  617.         /*
  618.          * We ran into a data block. If it is still alive bring it into
  619.          * the cache. 
  620.          */
  621.          fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  622.          startBlockOffset = blockOffset;
  623.          /*
  624.           * Liveness check.   First see if the version number is
  625.           * the same and the file is still allocated.
  626.           */
  627.           LFS_STATS_INC(lfsPtr->stats.layout.fileCleaned);
  628.          status = LfsDescMapGetVersion(lfsPtr, 
  629.             (int)fileSumPtr->fileNumber, &curTruncVersion);
  630.          if ((status == SUCCESS) && 
  631.          (curTruncVersion == fileSumPtr->truncVersion)) {
  632.         Fs_FileID fileID;
  633.         int      numBlocks;
  634.         Fsio_FileIOHandle *newHandlePtr;
  635.  
  636.             LFS_STATS_INC(lfsPtr->stats.layout.fileVersionOk);
  637.         /*
  638.          * So far so good.  File is allocated and version number 
  639.          * says it hasn't been deleted or truncated. Grap a 
  640.          * handle for the file a check to see if the blocks 
  641.          * are still a member of the file.
  642.          */
  643.         fileID.type = FSIO_LCL_FILE_STREAM;
  644.         fileID.serverID = rpc_SpriteID;
  645.         fileID.major = lfsPtr->domainPtr->domainNumber;
  646.         fileID.minor = fileSumPtr->fileNumber;
  647.         status = Fsio_LocalFileHandleInit(&fileID, (char *) NIL, 
  648.                     (Fsdm_FileDescriptor *) NIL, TRUE, 
  649.                     &newHandlePtr);
  650.         if (status == FS_WOULD_BLOCK) {
  651.             printf("Can't fetch handle for file %d for cleaning\n",
  652.                 fileSumPtr->fileNumber);
  653.  
  654.             LFS_STATS_INC(lfsPtr->stats.layout.cleanLockedHandle);
  655.             error = TRUE;
  656.             break;
  657.         }
  658.         if (status != SUCCESS) {
  659.             if (status == FS_FILE_NOT_FOUND) {
  660.             /*
  661.              * Someone just deleted the file out from under us.
  662.              */
  663.             LFS_STATS_INC(lfsPtr->stats.layout.cleanNoHandle);
  664.             goto noHandle;
  665.             }
  666.             LfsError(lfsPtr, status,
  667.                 "Can't get handle to clean file\n");
  668.         }
  669.         /*
  670.          * For each block ... 
  671.          */
  672.         blockArray = (int *)
  673.             (summaryPtr + sizeof(LfsFileLayoutSummary));
  674.         /*
  675.          * Careful with the first block because it could be a 
  676.          * fragment.
  677.          */
  678.         numBlocks = fileSumPtr->numBlocks - 
  679.                 (fileSumPtr->numDataBlocks-1) * fsBlocks;
  680.             LFS_STATS_ADD(lfsPtr->stats.layout.blocksCleaned,
  681.                     fileSumPtr->numBlocks);
  682.         for (i = 0; i < fileSumPtr->numDataBlocks; i++) {
  683.             LfsDiskAddr newDiskAddr;
  684.             blockOffset += numBlocks;
  685.             status = LfsFile_GetIndex(newHandlePtr, blockArray[i],
  686.                 FSCACHE_CANT_BLOCK|FSCACHE_DONT_BLOCK,
  687.                 &diskAddress);
  688.             LfsDiskAddrPlusOffset(address, -blockOffset, &newDiskAddr);
  689.             if ((status == SUCCESS) && 
  690.               LfsSameDiskAddr(diskAddress, newDiskAddr)) { 
  691.             int    blockSize, flags;
  692.             Boolean     found;
  693.             Fscache_Block *blockPtr;
  694.             /*
  695.              * The block exists and is at the location we are
  696.              * cleaning, bring it into the cache. Be a little
  697.              * careful about short blocks.
  698.              */
  699.                 LFS_STATS_ADD(lfsPtr->stats.layout.blocksCopied,numBlocks);
  700.                 blockSize = LfsBlocksToBytes(lfsPtr, numBlocks);
  701.             flags = (FSCACHE_IO_IN_PROGRESS | FSCACHE_CANT_BLOCK | 
  702.                         FSCACHE_DONT_BLOCK |
  703.                       ((blockArray[i] >= 0) ? FSCACHE_DATA_BLOCK :
  704.                               FSCACHE_IND_BLOCK));
  705.  
  706.                 Fscache_FetchBlock(&newHandlePtr->cacheInfo,
  707.                       blockArray[i], flags, &blockPtr, &found);
  708.             if (blockPtr == (Fscache_Block *) NIL) {
  709.                 printf("Can't fetch cache block <%d,%d> for cleaning.\n", fileSumPtr->fileNumber, blockArray[i]);
  710.                 error = TRUE;
  711.                 break;
  712.             }
  713.             if (!found) {
  714.                 char *dPtr;
  715.                 /*
  716.                  * Its not in the cache already, copy it in.
  717.                  * Handle the cache that it in a short fragment.
  718.                  */
  719.                 if (blockArray[i] >= 0) {
  720.                 if (blockArray[i] * FS_BLOCK_SIZE + 
  721.                         blockSize - 1 >
  722.                     newHandlePtr->descPtr->lastByte) {
  723.                     blockSize = newHandlePtr->descPtr->lastByte
  724.                     - blockArray[i] * FS_BLOCK_SIZE + 1;
  725.                 }
  726.                 } else if (blockSize != FS_BLOCK_SIZE) {
  727.                 panic("Illegal sized indirect block.\n");
  728.                 }
  729.                 if (blockSize <= 0) { 
  730.                 panic("Illegal sized block.\n");
  731.                 }
  732.  
  733.                 dPtr = LfsSegFetchBytes(segPtr, segPtr->curBlockOffset + blockOffset, 
  734.                     blockSize);
  735.                 bcopy(dPtr, blockPtr->blockAddr, blockSize);
  736.                 bzero(blockPtr->blockAddr + blockSize,
  737.                     FS_BLOCK_SIZE - blockSize);
  738.                 Fscache_UnlockBlock(blockPtr, Fsutil_TimeInSeconds(),
  739.                         -1, blockSize, 
  740.                         FSCACHE_BLOCK_BEING_CLEANED);
  741.  
  742.             } else { 
  743.                 /*
  744.                  * Checking it out.
  745.                  */
  746. #ifdef ERROR_CHECK
  747.                 char *dPtr;
  748.                 Boolean bad;
  749.                 dPtr = LfsSegFetchBytes(segPtr, blockOffset + segPtr->curBlockOffset, 
  750.                     blockSize);
  751.                 bad = bcmp(dPtr, blockPtr->blockAddr, 
  752.                     blockPtr->blockSize);
  753.                 if (bad && !(blockPtr->flags & FSCACHE_BLOCK_DIRTY)) {
  754.                 panic("Block cleaned doesn't match block.\n");
  755.                 }
  756. #endif
  757.                 Fscache_UnlockBlock(blockPtr, Fsutil_TimeInSeconds(),
  758.                         -1, blockPtr->blockSize, 
  759.                         FSCACHE_BLOCK_BEING_CLEANED);
  760.                LFS_STATS_ADD(lfsPtr->stats.layout.blocksCopiedHit,
  761.                     numBlocks);
  762.             }
  763.             (*sizePtr) += blockSize;
  764.             (*numCacheBlocksPtr)++;
  765.             } else if (status != SUCCESS) {
  766.             printf("Can't fetch index for cleaning <%d,%d>\n",
  767.                     fileSumPtr->fileNumber, blockArray[i]);
  768.             error = TRUE;
  769.             break;
  770.             }
  771.             /*
  772.              * All the blocks after the first one must be FS_BLOCK_SIZE.
  773.              */
  774.             numBlocks = fsBlocks;
  775.         }
  776.         Fsutil_HandleRelease(newHandlePtr, TRUE);
  777.         } else {
  778. #ifdef TRACING
  779.             {
  780.                 LfsTraceRecord rec;
  781.                 rec.fileNumber = fileSumPtr->fileNumber;
  782.                 rec.diskAddr = address;
  783.                 rec.status = status;
  784.                 rec.curTruncVersion = curTruncVersion;
  785.                 Trace_Insert(lfsTraceHdrPtr, 0, (ClientData)&rec);
  786.             }
  787. #endif /* TRACING */
  788.         }
  789.      noHandle:
  790.         blockOffset = startBlockOffset + fileSumPtr->numBlocks;
  791.         summaryPtr += sizeof(LfsFileLayoutSummary) + 
  792.                 fileSumPtr->numDataBlocks * sizeof(int); 
  793.         break;
  794.       }
  795.  
  796.     case LFS_FILE_LAYOUT_DIR_LOG: {
  797.         LfsFileLayoutLog    *logSumPtr;
  798.         /* 
  799.          * Directory log info is not needed during clean so we 
  800.          * just skip over it.
  801.          */
  802.          logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  803.          summaryPtr += sizeof(LfsFileLayoutLog);
  804.          blockOffset += logSumPtr->numBlocks;
  805.          break;
  806.     }
  807.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  808.     case LFS_FILE_LAYOUT_INDIRECT: 
  809.     default: {
  810.         panic("Unknown type");
  811.     }
  812.       }
  813.     }
  814.  
  815.     return error;
  816.  
  817. }
  818.  
  819. /*
  820.  *----------------------------------------------------------------------
  821.  *
  822.  * PlaceFileInSegment --
  823.  *
  824.  *    Place specified file dirty in segment.
  825.  *
  826.  * Results:
  827.  *    TRUE if the segment filled before the file was fully added.
  828.  *
  829.  * Side effects:
  830.  *    None.
  831.  *
  832.  *----------------------------------------------------------------------
  833.  */
  834. static Boolean 
  835. PlaceFileInSegment(lfsPtr, segPtr, cacheInfoPtr, layoutPtr, token,
  836.         segLayoutDataPtr)
  837.     Lfs        *lfsPtr;    /* File system. */
  838.     LfsSeg    *segPtr;    /* Segment to place data. */
  839.     Fscache_FileInfo *cacheInfoPtr;    /* File to place in segment. */
  840.     LfsFileLayout     *layoutPtr;   /* File layout info. */
  841.     int             token;        /* Block selector token. */
  842.     FileSegLayout  *segLayoutDataPtr; /* Current layout data for segment. */
  843. {
  844.     LfsFileLayoutSummary *fileSumPtr;
  845.     Boolean    full;
  846.     LfsSegElement    *bufferPtr;
  847.     char    *summaryPtr;
  848.     int        lfsBlocksPerBlock, lastDirtyBlock;
  849.     int        blockType;
  850.     int        blocksNeeded, bytesNeeded, blocksLeft;
  851.     ReturnStatus    status;
  852.     Fscache_Block    *blockPtr, *firstBlockPtr;
  853.     Fsdm_FileDescriptor *descPtr;
  854.  
  855.     if (cacheInfoPtr == (Fscache_FileInfo *) NIL) {
  856.     return FALSE;
  857.     }
  858.     descPtr = ((Fsio_FileIOHandle *)(cacheInfoPtr->hdrPtr))->descPtr;
  859.     /*
  860.      * Layout the blocks of the file into the segment starting with the
  861.      * data blocks.
  862.      */
  863.     full = FALSE;
  864.     fileSumPtr = (LfsFileLayoutSummary *) NIL;
  865.     lfsBlocksPerBlock = LfsBytesToBlocks(lfsPtr, FS_BLOCK_SIZE);
  866.     for (blockType = LFS_FILE_LAYOUT_DATA; 
  867.     (blockType <= LFS_FILE_LAYOUT_DBL_INDIRECT) && !full;  blockType++) { 
  868.     /*
  869.      * Do all of one blockType first before going to the next.
  870.      * Try to checkout just enought blocks that will fit in this
  871.      * segment. We prefetch the first block so that we know if
  872.      * we have zero blocks to layout and don't have to add a
  873.      * LfsFileLayoutSummary.
  874.      */
  875.     firstBlockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch,
  876.                 (ClientData) ((token << 16) | blockType),
  877.                  &lastDirtyBlock);
  878.     /*
  879.      * No more blocks of this type available for this file, go on to 
  880.      * the next blockType. 
  881.      */ 
  882.     if (firstBlockPtr == (Fscache_Block *) NIL) {
  883.         continue;
  884.     }
  885.     if ((firstBlockPtr->blockSize < FS_BLOCK_SIZE) && 
  886.         (firstBlockPtr->blockNum != descPtr->lastByte/FS_BLOCK_SIZE)) {
  887.         /*
  888.          * Only the last block in the file is allowed to be less than 
  889.          * FS_BLOCK_SIZE. Sometimes the Fscache_Block->blockSize
  890.          * is incorrect so we patch it for them.
  891.          */
  892.         firstBlockPtr->blockSize = FS_BLOCK_SIZE;
  893.     }
  894.  
  895.        /*
  896.         * Allocate the layout summary bytes of this file if 
  897.         * we haven't done so already.
  898.         */
  899.        if (fileSumPtr == (LfsFileLayoutSummary *) NIL) {
  900.        /*
  901.         * Since we haven't done so already, allocate a LfsFileLayoutSummary
  902.         * for this file in summary block.  Besure there is at least 
  903.         * enough space for one block. If the block that we justed got 
  904.         * (ie firstBlockPtr) is the last block in the cache we ensure
  905.         * that there is enough room for it.  Otherwise we require at 
  906.         * least a entire blocks worth.
  907.         */
  908.        blocksNeeded =  (lastDirtyBlock != 0) ? lfsBlocksPerBlock : 
  909.                 LfsBytesToBlocks(lfsPtr, 
  910.                         firstBlockPtr->blockSize);
  911.        bytesNeeded = sizeof(LfsFileLayoutSummary) + sizeof(int);
  912.        summaryPtr = LfsSegGrowSummary(segPtr, blocksNeeded, bytesNeeded);
  913.        if (summaryPtr == (char *) NIL) { 
  914.            /*
  915.             * No room in summary. Return block and exit loop.
  916.         */
  917.            Fscache_ReturnDirtyBlock(firstBlockPtr, GEN_EINTR);
  918.            full = TRUE;
  919.            break;
  920.        }
  921.        /*
  922.         * Fill in the LfsFileLayoutSummary with the value we 
  923.         * know now.
  924.         */
  925.        fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  926.        fileSumPtr->blockType = LFS_FILE_LAYOUT_DATA;
  927.        fileSumPtr->numDataBlocks = 0;
  928.        fileSumPtr->numBlocks = 0; /* Filled in later. */
  929.        fileSumPtr->fileNumber = cacheInfoPtr->hdrPtr->fileID.minor;
  930.        status = LfsDescMapGetVersion(lfsPtr, 
  931.                fileSumPtr->fileNumber, &fileSumPtr->truncVersion);
  932.        if (status != SUCCESS) {
  933.            LfsError(lfsPtr, status, "Can't get truncate version number\n");
  934.        }
  935.        summaryPtr += sizeof(LfsFileLayoutSummary);
  936.        LfsSegSetSummaryPtr(segPtr, summaryPtr);
  937.        }
  938.        /*
  939.         * Place the blocks in the segment in reverse order so that
  940.         * they will occur on disk in forward order. This is done
  941.     * by looping until we have collected enough blocks to fill the
  942.     * segments or we run out of cache blocks.  Note that we are
  943.     * permitted to overrun the segment because the code below will
  944.     * return the blocks to the cache.
  945.     *
  946.     * The first block we push on the list is the block we prefetched
  947.     * above.
  948.     */
  949.        blocksLeft = LfsSegBlocksLeft(segPtr);
  950.        blockPtr = firstBlockPtr;
  951.        do {  
  952.        LFS_STATS_INC(lfsPtr->stats.layout.dirtyBlocks);
  953.         if ((blockPtr->blockSize < FS_BLOCK_SIZE) && 
  954.         (blockPtr->blockNum != descPtr->lastByte/FS_BLOCK_SIZE)) {
  955.         /*
  956.          * Only the last block in the file is allowed to be less than 
  957.          * FS_BLOCK_SIZE. Sometimes the Fscache_Block->blockSize
  958.          * is incorrect so we patch it for them.
  959.          */
  960.         blockPtr->blockSize = FS_BLOCK_SIZE;
  961.         }
  962.        List_Insert((List_Links *) blockPtr, 
  963.             LIST_ATFRONT(&segLayoutDataPtr->blockList));
  964.        blocksLeft -= LfsBytesToBlocks(lfsPtr, blockPtr->blockSize);
  965.        if (blocksLeft > 0) {
  966.            blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, 
  967.             BlockMatch, (ClientData) ((token << 16) | blockType), 
  968.             &lastDirtyBlock);
  969.         }
  970.     } while ((blocksLeft > 0) && (blockPtr != (Fscache_Block *) NIL));
  971.  
  972.     /*
  973.      * Interate forward thru the blocks we pushed on the list to 
  974.      * lay them out in the reverse order.  We allow the first
  975.      * block to layout to be a fragment, so we start off by
  976.      * computing the number of fs blocks needed by the first
  977.      * cache block.
  978.      */
  979.     blockPtr = (Fscache_Block *) List_First(&segLayoutDataPtr->blockList);
  980.     blocksNeeded = LfsBytesToBlocks(lfsPtr, blockPtr->blockSize);
  981.  
  982.     LIST_FORALL(&segLayoutDataPtr->blockList, (List_Links *) blockPtr) {
  983.         int bytesUsed;
  984.         int modTime;
  985.        /*
  986.         * Make sure there is enough room for both the data blocks in 
  987.         * the data region and the block number in the summary region.
  988.         */
  989.        summaryPtr = LfsSegGrowSummary(segPtr, blocksNeeded, sizeof(int));
  990.        if (summaryPtr == (char *) NIL) {
  991.            full = TRUE;
  992.            break;
  993.        }
  994.        /*
  995.         * Yes there is; add the cache block and fill in the summary region.
  996.         * Update the LfsFileLayoutSummary to reflect the data block being
  997.         * added and the number of fs blocks used.
  998.         */
  999.        *(int *) summaryPtr = blockPtr->blockNum;
  1000.        summaryPtr += sizeof(int);
  1001.        LfsSegSetSummaryPtr(segPtr,summaryPtr);
  1002. #ifdef SOSP91
  1003.        Fscache_AddBlockToStats(cacheInfoPtr, blockPtr); 
  1004. #endif SOSP91
  1005.        bufferPtr = LfsSegAddDataBuffer(segPtr, blocksNeeded, 
  1006.                 blockPtr->blockAddr, (ClientData) blockPtr);
  1007.  
  1008.        fileSumPtr->numDataBlocks++; 
  1009.        fileSumPtr->numBlocks += blocksNeeded;
  1010.  
  1011.        /*
  1012.         * Update the index for this file and increment the 
  1013.         * active bytes of the segment by the size of the cache
  1014.         * block rounded to file system blocks.
  1015.         */
  1016.        bytesUsed = LfsBlocksToBytes(lfsPtr,
  1017.             LfsBytesToBlocks(lfsPtr, blockPtr->blockSize));
  1018.        status = LfsFile_SetIndex(
  1019.                 (Fsio_FileIOHandle *)(cacheInfoPtr->hdrPtr), 
  1020.                 blockPtr->blockNum, bytesUsed, 
  1021.                 FSCACHE_CANT_BLOCK,
  1022.                 LfsSegDiskAddress(segPtr, bufferPtr));
  1023.        if (status != SUCCESS) {
  1024.          blockPtr->flags |= FSCACHE_BLOCK_DIRTY;
  1025.          LfsError(lfsPtr, status, "Can't update file index");
  1026.        }
  1027.        segPtr->activeBytes += bytesUsed;
  1028.        /*
  1029.         * Update the modtime time of the segment to reflect this block
  1030.         * if it is under than the rest.
  1031.         */
  1032.        modTime = descPtr->dataModifyTime;
  1033.        if (segPtr->timeOfLastWrite < modTime) {
  1034.            segPtr->timeOfLastWrite = modTime;
  1035.        }
  1036.        /*
  1037.         * Any blocks after the first one must be of FS_BLOCK_SIZE 
  1038.         * size.
  1039.         */
  1040.        blocksNeeded = lfsBlocksPerBlock;
  1041.        /*
  1042.         * Stop going down the list when we get to the first block we
  1043.         * pushed on.
  1044.         */
  1045.        if (blockPtr == firstBlockPtr) {
  1046.         break;
  1047.        }
  1048.     } 
  1049.     if (full) { 
  1050.         while(1) {
  1051.         Fscache_Block *nextBlockPtr;
  1052.         /*
  1053.          * We're not able to place all the blocks, return to the cache
  1054.          * all blocks we couldn't place.
  1055.          */
  1056.         LFS_STATS_INC(lfsPtr->stats.layout.dirtyBlocksReturned);
  1057.         nextBlockPtr = (Fscache_Block *) 
  1058.                 List_Next((List_Links *)blockPtr);
  1059.         List_Remove((List_Links *) blockPtr);
  1060.         Fscache_ReturnDirtyBlock(blockPtr, GEN_EINTR);
  1061.         if (blockPtr == firstBlockPtr) {
  1062.             break;
  1063.         }
  1064.         blockPtr = nextBlockPtr;
  1065.         } 
  1066.     }
  1067.     }
  1068. #ifdef SOSP91
  1069.     cacheInfoPtr->flags &= ~FSCACHE_REASON_FLAGS;
  1070. #endif SOSP91
  1071.     if (full) { 
  1072.      return full;
  1073.     }
  1074.    /*
  1075.     * If the segment we are adding has no slots open in the descriptor
  1076.     * block try to allocate a new descriptor block.
  1077.     */
  1078.     if (segLayoutDataPtr->numDescSlotsLeft == 0) {
  1079.     LfsFileLayoutDesc    *descSumPtr;
  1080.     int        descBlocks, descBytes;
  1081.  
  1082.     /*
  1083.      * Compute the size and add the descriptor block.
  1084.      */
  1085.     descBytes = layoutPtr->params.descPerBlock * sizeof(LfsFileDescriptor);
  1086.     descBlocks = LfsBytesToBlocks(lfsPtr, descBytes);
  1087.  
  1088.     summaryPtr = LfsSegGrowSummary(segPtr, descBlocks, 
  1089.                         sizeof(LfsFileLayoutDesc));
  1090.     if (summaryPtr != (char *) NIL) {
  1091.         LfsSegElement *descBufferPtr;
  1092.         char      *descMemPtr;
  1093.         ClientData    clientData;
  1094.         /*
  1095.          * Allocate space for the descriptor block and fill in a
  1096.          * summary block describing it. 
  1097.          */
  1098.         descBufferPtr = LfsSegAddDataBuffer(segPtr, descBlocks,
  1099.                         (char *) NIL, (ClientData) NIL);
  1100.         segLayoutDataPtr->numDescSlotsLeft = layoutPtr->params.descPerBlock;
  1101.         segLayoutDataPtr->descDiskAddr = 
  1102.                 LfsSegDiskAddress(segPtr, descBufferPtr);
  1103.         descMemPtr = (char *) NIL;
  1104.         clientData = LfsDescCacheBlockInit(lfsPtr, 
  1105.                 segLayoutDataPtr->descDiskAddr, TRUE, 
  1106.                 &descMemPtr);
  1107.         segLayoutDataPtr->descBlockPtr = (LfsFileDescriptor *) descMemPtr;
  1108.         descBufferPtr->address = descMemPtr;
  1109.         descBufferPtr->clientData = clientData;
  1110.  
  1111.         descSumPtr = (LfsFileLayoutDesc *) summaryPtr;
  1112.  
  1113.         descSumPtr->blockType =  LFS_FILE_LAYOUT_DESC;
  1114.         descSumPtr->numBlocks = descBlocks;
  1115.  
  1116.         summaryPtr += sizeof(LfsFileLayoutDesc);
  1117.         LfsSegSetSummaryPtr(segPtr, summaryPtr);
  1118.  
  1119.     }
  1120.     }
  1121.     /*
  1122.      * If we successfully place this file in the segment add the descriptor
  1123.      * to the descriptor block. If this is no room then mark the segment 
  1124.      * as full.
  1125.      */
  1126.     if (segLayoutDataPtr->numDescSlotsLeft > 0) {
  1127.       /*
  1128.        * XXX - need to do this under lock. 
  1129.        */
  1130.       LFS_STATS_INC(lfsPtr->stats.layout.descWritten);
  1131.       cacheInfoPtr->flags &= ~FSCACHE_FILE_DESC_DIRTY;
  1132.       descPtr->flags &= ~FSDM_FD_DIRTY;    
  1133.       bcopy((char *) descPtr, 
  1134.         (char *)&(segLayoutDataPtr->descBlockPtr->common),
  1135.         (int)sizeof(*descPtr));
  1136.       segLayoutDataPtr->descBlockPtr->fileNumber = 
  1137.               cacheInfoPtr->hdrPtr->fileID.minor;
  1138.       status = LfsDescMapSetDiskAddr(lfsPtr, 
  1139.             (int)segLayoutDataPtr->descBlockPtr->fileNumber, 
  1140.             segLayoutDataPtr->descDiskAddr);
  1141.       if (status != SUCCESS) {
  1142.           LfsError(lfsPtr, status, "Can't update descriptor map.\n");
  1143.       }
  1144.       segLayoutDataPtr->descBlockPtr++;
  1145.       segLayoutDataPtr->numDescSlotsLeft--;
  1146.       segPtr->activeBytes += sizeof(LfsFileDescriptor);
  1147.      } else {
  1148.      full = TRUE;
  1149.      }
  1150.      return full;
  1151. }
  1152.  
  1153.  
  1154. /*
  1155.  * ----------------------------------------------------------------------------
  1156.  *
  1157.  * BlockMatch --
  1158.  *
  1159.  *     Cache backend block type match.  
  1160.  *
  1161.  * Results:
  1162.  *    TRUE.
  1163.  *
  1164.  * Side effects:
  1165.  *
  1166.  * ----------------------------------------------------------------------------
  1167.  */
  1168. /*ARGSUSED*/
  1169. static Boolean
  1170. BlockMatch(blockPtr, clientData)
  1171.     Fscache_Block *blockPtr;
  1172.     ClientData       clientData;
  1173. {
  1174.     int blockLevel = ((int) clientData) & 0xffff;
  1175.     int token = ((int) clientData) >> 16;
  1176.  
  1177.     /*
  1178.      * The match fails if:
  1179.      * a) We want a data block and the block is an indirect block.
  1180.      *      or
  1181.      * b) We want an indirect block and the blocks is a data or
  1182.      *      double indirect block.
  1183.      *        or
  1184.      * c) We want a double indirect block and don't get it.
  1185.      */
  1186.     if ( ((blockLevel == LFS_FILE_LAYOUT_DATA) && (blockPtr->blockNum < 0)) ||
  1187.      ((blockLevel == LFS_FILE_LAYOUT_INDIRECT) && 
  1188.         ((blockPtr->blockNum >= 0) || (blockPtr->blockNum == -2))) || 
  1189.      ((blockLevel == LFS_FILE_LAYOUT_DBL_INDIRECT) && 
  1190.          (blockPtr->blockNum != -2))) { 
  1191.     return FALSE;
  1192.     } 
  1193.  
  1194.     if (token == CLEANING_TOKEN) {
  1195.     return ((blockPtr->flags & FSCACHE_BLOCK_BEING_CLEANED) != 0);
  1196.     } else {
  1197.     return TRUE;
  1198.     }
  1199. }
  1200.  
  1201.  
  1202. /*
  1203.  * ----------------------------------------------------------------------------
  1204.  *
  1205.  * LfsFileMatch --
  1206.  *
  1207.  *     Cache backend file match for LFS.
  1208.  *
  1209.  * Results:
  1210.  *    TRUE.
  1211.  *
  1212.  * Side effects:
  1213.  *
  1214.  * ----------------------------------------------------------------------------
  1215.  */
  1216. /*ARGSUSED*/
  1217. Boolean
  1218. LfsFileMatch(cacheInfoPtr, clientData)
  1219.     Fscache_FileInfo *cacheInfoPtr;
  1220.     ClientData    clientData;
  1221. {
  1222.     register int token = (int) clientData;
  1223.  
  1224.     if ((token < 0) || (cacheInfoPtr->hdrPtr->fileID.minor < 0)) {
  1225.     return  (cacheInfoPtr->hdrPtr->fileID.minor == token);
  1226.     }
  1227.     if (token == WRITEBACK_TOKEN) { 
  1228.     return ((cacheInfoPtr->flags & FSCACHE_FILE_BEING_CLEANED) == 0);
  1229.     } 
  1230.     if (token == CLEANING_TOKEN) {
  1231.     return ((cacheInfoPtr->flags & FSCACHE_FILE_BEING_CLEANED) != 0);
  1232.     } 
  1233.     /*
  1234.      * Assume CHECKPOINT_TOKEN token.
  1235.      */
  1236.     return TRUE;
  1237. }
  1238. #undef LOCKPTR
  1239. #define LOCKPTR &lfsPtr->logLock
  1240.  
  1241. /*
  1242.  *----------------------------------------------------------------------
  1243.  *
  1244.  * LfsDirLogEntryAlloc --
  1245.  *
  1246.  *    Allocate a directory log entry for a directory change operation.
  1247.  *    NOTE: This routines assumes the callers has LOCKPTR held.
  1248.  *
  1249.  * Results:
  1250.  *    A pointer to the allocated LfsDirOpLogEntry structure.
  1251.  *
  1252.  * Side effects:
  1253.  *    None.
  1254.  *
  1255.  *----------------------------------------------------------------------
  1256.  */
  1257.  
  1258. LfsDirOpLogEntry *
  1259. LfsDirLogEntryAlloc(lfsPtr, entrySize, logSeqNum, foundPtr)
  1260.     Lfs        *lfsPtr;    /* LFS file system to allocate log entry for. */
  1261.     int        entrySize;    /* Size of log entry in bytes. */
  1262.     int        logSeqNum;    /* Log sequence number of entry. (-1) if new
  1263.                  * entry is needed. */
  1264.     Boolean    *foundPtr;    /* TRUE if logSeqNum award was found. */
  1265. {
  1266.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1267.     LfsDirOpLogEntry *entryPtr;
  1268.  
  1269.     if (logSeqNum != -1) {
  1270.     LFS_STATS_INC(lfsPtr->stats.dirlog.entryAllocOld);
  1271.     } else {
  1272.     LFS_STATS_INC(lfsPtr->stats.dirlog.entryAllocNew);
  1273.     }
  1274.     /*
  1275.      * Wait until we are no longer writing or laying out blocks.
  1276.      */
  1277.     while (dirLogPtr->paused) {
  1278.     LFS_STATS_INC(lfsPtr->stats.dirlog.entryAllocWaits);
  1279.     Sync_Wait(&dirLogPtr->logPausedWait, FALSE);
  1280.     }
  1281.     /*
  1282.      * If the caller wants a brand new log record or the specified 
  1283.      * log record has been flushed from memory.
  1284.      */
  1285.     entryPtr = (logSeqNum != -1) ? FindLogEntry(lfsPtr, logSeqNum) : 
  1286.                    (LfsDirOpLogEntry *) NIL;
  1287.     if (entryPtr == (LfsDirOpLogEntry *) NIL) {
  1288.     if (entrySize > dirLogPtr->bytesLeftInBlock) {
  1289.         LFS_STATS_INC(lfsPtr->stats.dirlog.newLogBlock);
  1290.         NewDirLogBlock(lfsPtr);
  1291.     }
  1292.     entryPtr = (LfsDirOpLogEntry *) dirLogPtr->nextBytePtr;
  1293.     entryPtr->hdr.logSeqNum = dirLogPtr->nextLogSeqNum++;
  1294.     dirLogPtr->nextBytePtr += entrySize;
  1295.     dirLogPtr->bytesLeftInBlock -= entrySize;
  1296.     dirLogPtr->curBlockHdrPtr->size += entrySize;
  1297.     *foundPtr = FALSE;
  1298.     return entryPtr;
  1299.     } 
  1300.     /*
  1301.      * Called wanted a previous entry that is still in memory.
  1302.      */
  1303.     LFS_STATS_INC(lfsPtr->stats.dirlog.entryAllocFound);
  1304.     *foundPtr = TRUE;
  1305.     return entryPtr;
  1306. }
  1307.  
  1308. /*
  1309.  *----------------------------------------------------------------------
  1310.  *
  1311.  * DirLogInit --
  1312.  *
  1313.  *    Initialize the directory change log for this LFS file system.
  1314.  *
  1315.  * Results:
  1316.  *    None.
  1317.  *
  1318.  * Side effects:
  1319.  *    None.
  1320.  *
  1321.  *----------------------------------------------------------------------
  1322.  */
  1323.  
  1324. static void
  1325. DirLogInit(lfsPtr)
  1326.     Lfs    *lfsPtr;    /* File system to initialize dir log for. */
  1327. {
  1328.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1329.     Fscache_Attributes        attr;
  1330.  
  1331.     dirLogPtr->nextLogSeqNum = 0;
  1332.     dirLogPtr->curBlockHdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  1333.     dirLogPtr->nextBytePtr = (char *) NIL;
  1334.     dirLogPtr->bytesLeftInBlock = 0;
  1335.     List_Init(&dirLogPtr->activeListHdr);
  1336.     List_Init(&dirLogPtr->writingListHdr);
  1337.     /*
  1338.      * Initialize the file handle used to create descriptor blocks under
  1339.      */
  1340.     bzero((char *)(&dirLogPtr->handle),sizeof(dirLogPtr->handle));
  1341.     dirLogPtr->handle.hdr.fileID.major = lfsPtr->domainPtr->domainNumber;
  1342.     dirLogPtr->handle.hdr.fileID.minor = -1024;
  1343.     dirLogPtr->handle.hdr.fileID.type = FSIO_LCL_FILE_STREAM;
  1344.     dirLogPtr->handle.descPtr = (Fsdm_FileDescriptor *)NIL;
  1345.  
  1346.     bzero((Address)&attr, sizeof(attr));
  1347.     attr.lastByte = 0x7fffffff;
  1348.     Fscache_FileInfoInit(&dirLogPtr->handle.cacheInfo,
  1349.             (Fs_HandleHeader *) &dirLogPtr->handle,
  1350.             0, TRUE, &attr, lfsPtr->domainPtr->backendPtr);
  1351.     dirLogPtr->leastCachedSeqNum = 0;
  1352.     dirLogPtr->paused = FALSE;
  1353. }
  1354.  
  1355. /*
  1356.  *----------------------------------------------------------------------
  1357.  *
  1358.  * DirLogDestory --
  1359.  *
  1360.  *    Free up the directory change log for this LFS file system.
  1361.  *
  1362.  * Results:
  1363.  *    None.
  1364.  *
  1365.  * Side effects:
  1366.  *    None.
  1367.  *
  1368.  *----------------------------------------------------------------------
  1369.  */
  1370.  
  1371. static void
  1372. DirLogDestory(lfsPtr)
  1373.     Lfs    *lfsPtr;    /* File system to initialize dir log for. */
  1374. {
  1375.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1376.  
  1377.     if (!List_IsEmpty(&dirLogPtr->activeListHdr) || 
  1378.     !List_IsEmpty(&dirLogPtr->writingListHdr) ||
  1379.     (dirLogPtr->curBlockHdrPtr !=  (LfsDirOpLogBlockHdr *) NIL)) {
  1380.     LfsError(lfsPtr, FAILURE,
  1381.         "DirLogDestory - directory log still active\n");
  1382.     return;
  1383.     }
  1384.  
  1385.     Fscache_FileInvalidate(&dirLogPtr->handle.cacheInfo, 0, FSCACHE_LAST_BLOCK);
  1386. }
  1387.  
  1388. /*
  1389.  *----------------------------------------------------------------------
  1390.  *
  1391.  * NewDirLogBlock --
  1392.  *
  1393.  *    Add a new directory change log blocks to the currently going log.
  1394.  *    This routine should be called when a log entry needs to be added 
  1395.  *    yet doesn't fit.
  1396.  *
  1397.  * Results:
  1398.  *    None.
  1399.  *
  1400.  * Side effects:
  1401.  *    Fscache_Block blocks fetched from cache and put on activeList.
  1402.  *
  1403.  *----------------------------------------------------------------------
  1404.  */
  1405. static void
  1406. NewDirLogBlock(lfsPtr)
  1407.     Lfs    *lfsPtr;    /* File system of add dir log block for. */
  1408. {
  1409.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1410.     LfsDirOpLogBlockHdr *curBlockHdrPtr;
  1411.     Fscache_Block    *blockPtr;
  1412.     Boolean    found;
  1413.  
  1414.  
  1415.    Fscache_FetchBlock(&dirLogPtr->handle.cacheInfo,
  1416.         dirLogPtr->nextLogSeqNum, (FSCACHE_DESC_BLOCK|FSCACHE_DONT_BLOCK|FSCACHE_CANT_BLOCK),
  1417.             &blockPtr, &found);
  1418.    if (blockPtr == (Fscache_Block *) NIL) {
  1419.     LfsError(lfsPtr, FAILURE, "No space for dir log block in cache");
  1420.     return;
  1421.    }
  1422.    if (found) {
  1423.     LfsError(lfsPtr, FAILURE, "Found dir log block in cache");
  1424.    }
  1425.    curBlockHdrPtr = dirLogPtr->curBlockHdrPtr =  
  1426.                 (LfsDirOpLogBlockHdr *) blockPtr->blockAddr;
  1427.  
  1428.    curBlockHdrPtr->magic = LFS_DIROP_LOG_MAGIC;
  1429.    curBlockHdrPtr->size = sizeof(LfsDirOpLogBlockHdr);
  1430.    curBlockHdrPtr->nextLogBlock = 0;
  1431.    curBlockHdrPtr->reserved = 0;
  1432.    dirLogPtr->nextBytePtr = (char *) (curBlockHdrPtr+1);
  1433.    dirLogPtr->bytesLeftInBlock = FS_BLOCK_SIZE - sizeof(LfsDirOpLogBlockHdr);
  1434.    List_Insert((List_Links *) blockPtr, LIST_ATREAR(&dirLogPtr->activeListHdr));
  1435. }
  1436.  
  1437. /*
  1438.  *----------------------------------------------------------------------
  1439.  *
  1440.  * FindLogEntry --
  1441.  *
  1442.  *    Find a directory change operation log entry in the in memory 
  1443.  *    log buffers.
  1444.  *
  1445.  * Results:
  1446.  *    None.
  1447.  *
  1448.  * Side effects:
  1449.  *    None.
  1450.  *
  1451.  *----------------------------------------------------------------------
  1452.  */
  1453. static LfsDirOpLogEntry *
  1454. FindLogEntry(lfsPtr, logSeqNum)
  1455.     Lfs    *lfsPtr;    /* File system containing directory log. */
  1456.     int    logSeqNum;    /* Log sequent number we are looking for. */
  1457. {
  1458.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1459.     Fscache_Block *blockPtr;
  1460.     LfsDirOpLogEntry *entryPtr, *limitPtr;
  1461.     LfsDirOpLogBlockHdr *curBlockHdrPtr;
  1462.  
  1463.     if (logSeqNum < dirLogPtr->leastCachedSeqNum) {
  1464.     LFS_STATS_INC(lfsPtr->stats.dirlog.fastFindFail);
  1465.     return (LfsDirOpLogEntry *) NIL;
  1466.     }
  1467.  
  1468.     blockPtr = (Fscache_Block *) List_Last(&dirLogPtr->activeListHdr);
  1469.     while(1) {  
  1470.     if (blockPtr->blockNum <= logSeqNum) {
  1471.         curBlockHdrPtr = (LfsDirOpLogBlockHdr *) blockPtr->blockAddr;
  1472.         limitPtr = (LfsDirOpLogEntry *) 
  1473.                 (blockPtr->blockAddr + curBlockHdrPtr->size);
  1474.         entryPtr = (LfsDirOpLogEntry *) (curBlockHdrPtr + 1);
  1475.         while (entryPtr < limitPtr) { 
  1476.         LFS_STATS_INC(lfsPtr->stats.dirlog.findEntrySearch);
  1477.         if (entryPtr->hdr.logSeqNum == logSeqNum) {
  1478.             return entryPtr;
  1479.         }
  1480.         entryPtr = (LfsDirOpLogEntry *) 
  1481.                 (((char *) entryPtr) + 
  1482.                     LFS_DIR_OP_LOG_ENTRY_SIZE(entryPtr));
  1483.         }
  1484.     }
  1485.     if (blockPtr == (Fscache_Block *)List_First(&dirLogPtr->activeListHdr)){
  1486.         LfsError(lfsPtr, FAILURE, "Can't fine log entry in log.\n");
  1487.         break;
  1488.     }
  1489.     blockPtr = (Fscache_Block *) List_Prev((List_Links *) blockPtr);
  1490.     }
  1491.  
  1492.     return (LfsDirOpLogEntry *) NIL;
  1493.  
  1494. }
  1495.  
  1496. /*
  1497.  *----------------------------------------------------------------------
  1498.  *
  1499.  * AddDirLogBlocks --
  1500.  *
  1501.  *    Add a directory change log blocks to a segment to be written.
  1502.  *
  1503.  * Results:
  1504.  *    TRUE if we filled up the segment. False otherwise.
  1505.  *
  1506.  * Side effects:
  1507.  *    Fscache_Blocks are moved from the activeList to the writingList.
  1508.  *
  1509.  *----------------------------------------------------------------------
  1510.  */
  1511. static Boolean
  1512. AddDirLogBlocks(lfsPtr, segPtr, segLayoutDataPtr)
  1513.     Lfs        *lfsPtr;    /* File system. */
  1514.     LfsSeg    *segPtr;    /* Segment to place data. */
  1515.     FileSegLayout  *segLayoutDataPtr; /* Layout data of segment. */
  1516. {
  1517.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1518.     Fscache_Block *blockPtr;
  1519.     LfsDirOpLogBlockHdr *curBlockHdrPtr;
  1520.     LfsFileLayoutLog  *sumPtr;
  1521.     int        blocks;
  1522.     LOCK_MONITOR;
  1523.     sumPtr = (LfsFileLayoutLog *) NIL;
  1524.     while (!List_IsEmpty(&dirLogPtr->activeListHdr)) {
  1525.        LfsSegElement *elementPtr;
  1526.        blockPtr = (Fscache_Block *) List_First(&dirLogPtr->activeListHdr);
  1527.        curBlockHdrPtr = (LfsDirOpLogBlockHdr *) blockPtr->blockAddr;
  1528.        blocks = LfsBytesToBlocks(lfsPtr, curBlockHdrPtr->size);
  1529.        if (sumPtr == (LfsFileLayoutLog *) NIL) {
  1530.            sumPtr = (LfsFileLayoutLog *) LfsSegGrowSummary(segPtr, blocks, 
  1531.                 sizeof(LfsFileLayoutLog));
  1532.            if (sumPtr == (LfsFileLayoutLog *) NIL) {
  1533.             UNLOCK_MONITOR;
  1534.             return TRUE;
  1535.            }
  1536.            sumPtr->blockType = LFS_FILE_LAYOUT_DIR_LOG;
  1537.            sumPtr->numDataBlocks = 0;
  1538.            sumPtr->numBlocks = 0; /* Filled in later. */
  1539.            sumPtr->reserved = 0;
  1540.            dirLogPtr->paused = TRUE;
  1541.        }
  1542.        LfsSegSetSummaryPtr(segPtr, (char *) (sumPtr+1));
  1543.        elementPtr = LfsSegAddDataBuffer(segPtr, blocks, 
  1544.                 blockPtr->blockAddr, (ClientData) blockPtr);
  1545.        if (elementPtr == (LfsSegElement *) NIL) {
  1546.             /*
  1547.          * Could not fit block in segment.
  1548.          */
  1549.         UNLOCK_MONITOR;
  1550.         return TRUE;
  1551.         }
  1552.        sumPtr->numDataBlocks++; 
  1553.        sumPtr->numBlocks += blocks;
  1554.        LFS_STATS_INC(lfsPtr->stats.dirlog.dataBlockWritten);
  1555.        LFS_STATS_ADD(lfsPtr->stats.dirlog.blockWritten, blocks);
  1556.        LFS_STATS_ADD(lfsPtr->stats.dirlog.bytesWritten, 
  1557.             curBlockHdrPtr->size);
  1558.  
  1559.        List_Move((List_Links *) blockPtr, &segLayoutDataPtr->dirLogListHdr);
  1560.        if  (curBlockHdrPtr == dirLogPtr->curBlockHdrPtr) {
  1561.         dirLogPtr->curBlockHdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  1562.         dirLogPtr->nextBytePtr = (char *) NIL;
  1563.         dirLogPtr->bytesLeftInBlock = 0;
  1564.        }
  1565.     }
  1566.     UNLOCK_MONITOR;
  1567.     return FALSE;
  1568.  
  1569. }
  1570.  
  1571. /*
  1572.  *----------------------------------------------------------------------
  1573.  *
  1574.  * FreeDirLogBlocks --
  1575.  *
  1576.  *    Free directory log blocks that were written to disk.
  1577.  *
  1578.  * Results:
  1579.  *    None.
  1580.  *
  1581.  * Side effects:
  1582.  *    Fscache_Blocks on writingList are deleted from cache.
  1583.  *
  1584.  *----------------------------------------------------------------------
  1585.  */
  1586. static void
  1587. FreeDirLogBlocks(lfsPtr, segPtr, segLayoutDataPtr)
  1588.     Lfs        *lfsPtr;    /* File system. */
  1589.     LfsSeg    *segPtr;    /* Segment to place data. */
  1590.     FileSegLayout  *segLayoutDataPtr; /* Layout data of segment. */
  1591. {
  1592.     LfsDirLog *dirLogPtr = &lfsPtr->dirLog;
  1593.     Fscache_Block *blockPtr;
  1594.  
  1595.     LOCK_MONITOR;
  1596.     dirLogPtr->leastCachedSeqNum = dirLogPtr->nextLogSeqNum;
  1597.     while (!List_IsEmpty(&segLayoutDataPtr->dirLogListHdr)) {
  1598.     blockPtr = (Fscache_Block *) 
  1599.             List_First(&segLayoutDataPtr->dirLogListHdr);
  1600.     List_Remove((List_Links *)blockPtr);
  1601.     Fscache_UnlockBlock(blockPtr, 0, -1, 0, FSCACHE_DELETE_BLOCK);
  1602.     }
  1603.     dirLogPtr->paused = FALSE;
  1604.     Sync_Broadcast(&dirLogPtr->logPausedWait);
  1605.     UNLOCK_MONITOR;
  1606. }
  1607.  
  1608.  
  1609.